package com.yj.springbootsecuritydemo01.thread;

import lombok.SneakyThrows;

import java.util.LinkedList;

/**
 * 生产者消费者模型
 */
public class ProductFactory {


    private static LinkedList list = new LinkedList();


    public boolean isEmpty() {
        return list.size() == 0;
    }

    public boolean isFull() {
        return list.size() == 10;
    }

    //producer
    public synchronized void produce(String name) {

        while (list.size() == 10) {
            try {
                System.out.println("当前队列为满");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
            list.add("商品" + name);
            System.out.println("线程(" + Thread.currentThread().getName() + ")生产了一件产品:" +name+ ";当前剩余商品" + list.size() + "个");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            notify();
    }

    public synchronized void consume() {
        while (list.size() == 0) {
            System.out.println("当前队列为空");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
            try {
                Thread.sleep(5000);//根据需求为了便于观察结果，每消费一个产品，sleep 5000 ms
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String shop = (String) list.removeLast();
            System.out.println("线程(" + Thread.currentThread().getName() + ")消费了一件产品:" + shop + ";当前剩余商品" + list.size() + "个");
            notify();// 通知生产者继续生产
    }

    public static void main(String[] args) throws InterruptedException {
        ProductFactory productFactory = new ProductFactory();
        Producer producer = new Producer(productFactory);
        Consumer consumer = new Consumer(productFactory);
        Thread t1 = new Thread(producer);
        Thread t2 = new Thread(consumer);

        t1.start();
        t2.start();
    }
}

class Producer implements Runnable {

    private ProductFactory productFactory;

    public Producer(ProductFactory productFactory) {
        this.productFactory = productFactory;
    }

    @Override
    public void run() {
        int i = 0;
        while (true) {
            productFactory.produce(String.valueOf(i++)); //根据需求 ，调用 productFactory 的 produce 方法
        }

    }
}


class Consumer implements Runnable {

    private ProductFactory productFactory;

    public Consumer(ProductFactory productFactory) {
        this.productFactory = productFactory;
    }

    @Override
    public void run() {
        while (true) {

            productFactory.consume();

        }

    }
}

class ProductFactory1 {
    private LinkedList<String> products; //根据需求定义库存，用 LinkedList 实现
    private int capacity = 10; // 根据需求：定义最大库存 10

    public ProductFactory1() {
        products = new LinkedList<String>();
    }

    // 根据需求：produce 方法创建
    public synchronized void produce(String product) {
        while (capacity == products.size()) { //根据需求：如果达到 10 库存，停止生产
            try {
                System.out.println("警告：线程(" + Thread.currentThread().getName() + ")准备生产产品，但产品池已满");
                wait(); // 库存达到 10 ，生产线程进入 wait 状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        products.add(product); //如果没有到 10 库存，进行产品添加
        try {
            Thread.sleep(5000); //根据需求为了便于观察结果，每生产一个产品，sleep 5000 ms
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程(" + Thread.currentThread().getName() + ")生产了一件产品:" + product + ";当前剩余商品" + products.size() + "个");
        notify(); //生产了产品，通知消费者线程从 wait 状态唤醒，进行消费
    }

    // 根据需求：consume 方法创建
    public synchronized String consume() {
        while (products.size() == 0) { //根据需求：没有库存消费者进入wait状态
            try {
                System.out.println("警告：线程(" + Thread.currentThread().getName() + ")准备消费产品，但当前没有产品");
                wait(); //库存为 0 ，无法消费，进入 wait ，等待生产者线程唤醒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        String product = products.remove(0); //如果有库存则消费，并移除消费掉的产品
        try {
            Thread.sleep(5000);//根据需求为了便于观察结果，每消费一个产品，sleep 5000 ms
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程(" + Thread.currentThread().getName() + ")消费了一件产品:" + product + ";当前剩余商品" + products.size() + "个");
        notify();// 通知生产者继续生产
        return product;
    }
}
